% 参数说明：个体1、个体2、交叉率、喂料器染色体交叉数量、组内交叉数量
% 根据原始论文的代码有个疑问：ce作为元件分组序列染色体应该只需要组间交叉就行了，而组内交叉交给pc和gc就行了，
% 两条再解码就能实现组内、组间元件都改变
%% 23年10月7日改：因对元件分组序列ce进行交叉，会出现相同元件序号，导致Dis_Sum函数内Match_LambIndex为多个数，
%% 更新吸头坐标会出现维数不一致问题
function [lif1,lif2] = Cross(t,T,self,li1,li2,cross_rate,FeCrossNum,InterCrossNum)
    if (unifrnd (0,1) < cross_rate)
        se = randperm(2,1);
        % #################################################################
        if se == 1 %使用基础交叉算子1
            %ce若进行遗传操作，会出现ce内含有相同元件序号，因此不应该对ce操作！！！
             r = randperm(length(li1.ce(:,1)),1);%随机选择一个循环进行父代的交叉
            temp = li2.ce(r,:);
            li2.ce(r,:) = li1.ce(r,:);
            li1.ce(r,:) = temp;
            
            temp = li2.pc(r,:);
            li2.pc(r,:) = li1.pc(r,:);
            li1.pc(r,:) = temp;
            
            temp = li2.gc(r,:);
            li2.gc(r,:) = li1.gc(r,:);
            li1.gc(r,:) = temp;
            % 组内交叉
            is = randperm(length(li1.pc(1,:)),InterCrossNum);
            for j = 1:InterCrossNum
                temp = li2.pc(r,j);
                if temp==0 || li1.pc(r,j) == 0
                    %排除0
                else
                    li2.pc(r,j) = li1.pc(r,j);
                    li1.pc(r,j) = temp;
                end
            end
            
              for j = 1:InterCrossNum
                temp = li2.gc(r,j);
                if temp==0 || li1.gc(r,j) == 0
                    %排除0
                else
                    li2.gc(r,j) = li1.pc(r,j);
                    li1.gc(r,j) = temp;
                end
              end
            
        end
        %% 喂料器交叉
         if se == 2
%              if t<2/3*T 
                %% 分段交叉数量
%                  if t<1/3*T 
                     FeCrossNum = 4;
%                  else
%                       FeCrossNum = 2;
%                  end
                %% log交叉函数
%                 FeCrossNum = round(log((T))+log((T))/2-t*log((T))/T);%每一代的群体数量计算
            %% 固定交叉数量
                 fs = randperm(self.nK,FeCrossNum);
                 for i = 1:FeCrossNum
                     temp = li2.fc(fs(i));
                     li2.fc(fs(i)) = li1.fc(fs(i));
                     li1.fc(fs(i)) = temp;
                 end
                     
              
%              else
                %% 前半段进行随机交叉
%                  fs = randperm(floor(self.nK/2),FeCrossNum);
%                  for i = 1:FeCrossNum
%                      temp = li2.fc(fs(i));
%                      li2.fc(fs(i)) = li1.fc(fs(i));
%                      li1.fc(fs(i)) = temp;
%                  end
                 %% 后半段进行随机交叉
%                  fs = randi([floor(self.nK/2),self.nK],1,FeCrossNum);
%                  for i = 1:FeCrossNum
%                      temp = li2.fc(fs(i));
%                      li2.fc(fs(i)) = li1.fc(fs(i));
%                      li1.fc(fs(i)) = temp;
%                  end
%              end
%               else %当前迭代次数大于三分之二则使用新的交叉算子更新喂料器
%                    [li1,li2] = new_cross(self,li1,li2);
             %% 在子代1喂料器随机选择的序号周围进行交换
%                 S = round(log(T)+log(T)/2-t*log(T)/T);%每一代的群体数量计算
%                 FeCrossNum = 2;
%                 rand_pos = 2;
%                 fs = randi([ceil(rand_pos/2+2),length(li1.fc)-rand_pos-2],rand_pos,1);%rand_pos个随机点
%                 for i =1:rand_pos
%                     randIndex = randperm(FeCrossNum,FeCrossNum);%随机排序号
%                     fc1_choose = li1.fc(fs(i)-ceil(FeCrossNum/2):fs(i)+floor(FeCrossNum/2)-1);
%                     fc1_choose = fc1_choose(randIndex);
%                     li1.fc(fs(i)-ceil(FeCrossNum/2):fs(i)+floor(FeCrossNum/2)-1) = fc1_choose;
%                 end
%                 %% 
%                 zeta = decode(li1.ce,li1.gc); %贴头元器件的分配zeta（ce、gc）
%                 zeta_type = decode_compo_to_type(self,li1.gc);
%                 for i = 1:length(zeta(:,1))
%                     for j = 1:length(zeta(i,:))
%                         match_type = find(cellfun(@(x) ismember(zeta(i,j),x),self.type_num(:,3))); %元件对应的元件类型
%                         if length(match_type) == 0
%                             zeta_type(i,j) = 0;
%                         else
%                             zeta_type(i,j)  = match_type;
%                         end
%                     end
%                 end
%                 for j = 1:rand_pos
%                         [gc_row,gc_col] = find(zeta_type ==fs(j));%找到元件在gc解码的元件类型序列的位置（也等于gc编码的位置）
%                         ran = randperm(length(gc_row),1);
%                         ran = 1;
%                         gc_row = gc_row(ran);
%                         gc_col = gc_col(ran);
% 
%                         if gc_col<4
%                             temp = li1.gc(gc_row,gc_col);
%                             li1.gc(gc_row,gc_col) = li1.gc(gc_row,gc_col+1);
%                             li1.gc(gc_row,gc_col+1) = temp;
%                         end
% 
%                   end
%                    
%                    %% 在子代2喂料器随机选择的序号周围进行交换
%                     fs = randi([ceil(rand_pos/2+2),length(li1.fc)-rand_pos],rand_pos,1);%rand_pos个随机点
%                     for i =1:rand_pos
%                         randIndex = randperm(FeCrossNum,FeCrossNum);%随机排序
%                         fc1_choose = li2.fc(fs(i)-ceil(FeCrossNum/2):fs(i)+floor(FeCrossNum/2)-1);
%                         fc1_choose = fc1_choose(randIndex);
%                         li2.fc(fs(i)-ceil(FeCrossNum/2):fs(i)+floor(FeCrossNum/2)-1) = randIndex;
%                     end
%                  %% 在子代2gc随机选择的序号周围进行交换
%                    % 同喂料器选择的FeCrossNum个随机点，找到每个随机点对应gc的循环，将该循环的元件再随机排列
%                      for j = 1:rand_pos
%                         [gc_row,gc_col] = find(zeta_type ==fs(j));%找到元件在gc解码的元件类型序列的位置（也等于gc编码的位置）
%                         ran = randperm(length(gc_row),1);
%                         ran = 1;
%                         gc_row = gc_row(ran);
%                         gc_col = gc_col(ran);
%                         if gc_col<4
%                             temp = li2.gc(gc_row,gc_col);
%                             li2.gc(gc_row,gc_col) = li2.gc(gc_row,gc_col+1);
%                             li2.gc(gc_row,gc_col+1) = temp;
%                         end
%                      end
                   
                  
                     
                     
             end
%          end 
    end
        
    lif1 = li1;
    lif2 = li2;

end
